home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Utilities Experience
/
The Utilities Experience - Volume 1.iso
/
software
/
datatypes
/
aiff
/
source
/
libcode.c
< prev
next >
Wrap
C/C++ Source or Header
|
1978-06-29
|
8KB
|
397 lines
/*
** AIFF DataType
**
** Written by Olaf `Olsen' Barthel <olsen@sourcery.han.de>
** Public domain
**
** :ts=4
*/
#include "Data.h"
// Mandatory library routines
struct ClassBase * __asm __saveds LibInit(register __a0 BPTR LibSegment,register __d0 struct ClassBase *ClassBase,register __a6 struct ExecBase *ExecBase);
struct ClassBase * __asm __saveds LibOpen(register __a6 struct ClassBase *Base);
BPTR __asm __saveds LibExpunge(register __a6 struct ClassBase *Base);
BPTR __asm __saveds LibClose(register __a6 struct ClassBase *Base);
LONG __asm __saveds LibNull(register __a6 struct ClassBase *Base);
// The only user-callable routine
Class * __asm __saveds GetClassEngine(register __a6 struct ClassBase *ClassBase);
// Library header data, defined in "RomTag.asm"
extern UWORD __far LibVersion,
LibRevision;
extern UBYTE __far LibName[],
LibID[];
// Vector initialization table
APTR LibVectors[] =
{
LibOpen,
LibClose,
LibExpunge,
LibNull,
GetClassEngine,
(APTR)-1
};
// Library initialization table for MakeLibrary()
struct { ULONG DataSize; APTR Table; APTR Data; struct ClassBase * (*Init)(); } __aligned LibInitTab =
{
sizeof(struct ClassBase),
LibVectors,
NULL,
LibInit
};
/* AsyncStreamHandler():
*
* A special stream handler for use with iffparse.library and the
* asyncio routines.
*/
STATIC LONG __saveds __asm
AsyncStreamHandler(register __a0 struct Hook *Hook,register __a2 struct IFFHandle *Handle,register __a1 struct IFFStreamCmd *ActionPkt)
{
struct AsyncFile *Stream = (struct AsyncFile *)Handle -> iff_Stream;
LONG Bytes = ActionPkt -> sc_NBytes;
switch(ActionPkt -> sc_Command)
{
case IFFCMD_READ:
return(ReadAsync(Stream,ActionPkt -> sc_Buf,Bytes) != Bytes);
case IFFCMD_WRITE:
return(WriteAsync(Stream,ActionPkt -> sc_Buf,Bytes) != Bytes);
case IFFCMD_SEEK:
return(SeekAsync(Stream,Bytes,MODE_CURRENT) == -1);
default:
return(0);
}
}
/* LibInit():
*
* Initialize the library.
*/
struct ClassBase * __asm __saveds
LibInit(register __a0 BPTR LibSegment,register __d0 struct ClassBase *ClassBase,register __a6 struct ExecBase *ExecBase)
{
// Set up the header data
ClassBase -> LibNode . lib_Node . ln_Type = NT_LIBRARY;
ClassBase -> LibNode . lib_Node . ln_Name = LibName;
ClassBase -> LibNode . lib_Flags = LIBF_CHANGED | LIBF_SUMUSED;
ClassBase -> LibNode . lib_Version = LibVersion;
ClassBase -> LibNode . lib_Revision = LibRevision;
ClassBase -> LibNode . lib_IdString = LibID;
// Remember the segment pointer
Segment = LibSegment;
// Remember the exec library base pointer
SysBase = ExecBase;
// Initialize the shared data access semaphore
InitSemaphore(&LockSemaphore);
// Now take care of the IFFHandle I/O hook.
AsyncHook . h_Entry = (HOOKFUNC)AsyncStreamHandler;
return(ClassBase);
}
/* LibOpen(register __a6 struct ClassBase *ClassBase):
*
* Open the library, as called via OpenLibrary()
*/
struct ClassBase * __asm __saveds
LibOpen(register __a6 struct ClassBase *ClassBase)
{
// Increment usage count
ClassBase -> LibNode . lib_OpenCnt++;
// Prevent delayed expunge
ClassBase -> LibNode . lib_Flags &= ~LIBF_DELEXP;
// Is this the first initialization?
if(ClassBase -> LibNode . lib_OpenCnt == 1)
{
// We are going to modify data while in multitasking,
// so watch out
ObtainSemaphore(&LockSemaphore);
// Open libraries & classes
if(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",39))
{
if(IntuitionBase = OpenLibrary("intuition.library",39))
{
if(UtilityBase = OpenLibrary("utility.library",39))
{
if(IFFParseBase = OpenLibrary("iffparse.library",39))
{
if(DataTypesBase = OpenLibrary("datatypes.library",39))
{
if(SuperClassBase = OpenLibrary("datatypes/sound.datatype",39))
{
// Create a new class
if(SoundClass = MakeClass(ClassBase -> LibNode . lib_Node . ln_Name,SOUNDDTCLASS,NULL,NULL,NULL))
{
extern Object * __saveds __asm ClassDispatch(register __a0 Class *class,register __a2 Object *object,register __a1 Msg msg);
// Link the class dispatcher into it
// and keep a pointer to the library
// base
SoundClass -> cl_Dispatcher . h_Entry = (HOOKFUNC)ClassDispatch;
SoundClass -> cl_UserData = (ULONG)ClassBase;
// Make the class publicly available
AddClass(SoundClass);
// Release the lock
ReleaseSemaphore(&LockSemaphore);
// Return the library base pointer
return(ClassBase);
}
// Clean up...
CloseLibrary(SuperClassBase);
SuperClassBase = NULL;
}
CloseLibrary(DataTypesBase);
DataTypesBase = NULL;
}
CloseLibrary(IFFParseBase);
IFFParseBase = NULL;
}
CloseLibrary(UtilityBase);
UtilityBase = NULL;
}
CloseLibrary(IntuitionBase);
IntuitionBase = NULL;
}
CloseLibrary(DOSBase);
DOSBase = NULL;
}
// Release the lock
ReleaseSemaphore(&LockSemaphore);
// No success
return(NULL);
}
else
return(ClassBase);
}
/* LibExpunge(register __a6 struct ClassBase *ClassBase):
*
* Expunge the library, remove it from memory
*/
BPTR __asm __saveds
LibExpunge(register __a6 struct ClassBase *ClassBase)
{
// No more callers have the library open?
if(!ClassBase -> LibNode . lib_OpenCnt && Segment)
{
// Remember the segment pointer, so it can be unloaded
BPTR TempSegment = Segment;
// Remove the library from the public list
Remove(ClassBase);
// Free the vector table and the library data
FreeMem((BYTE *)ClassBase - ClassBase -> LibNode . lib_NegSize,ClassBase -> LibNode . lib_NegSize + ClassBase -> LibNode . lib_PosSize);
// Return the segment pointer
return(TempSegment);
}
else
{
// Expunge it later
ClassBase -> LibNode . lib_Flags |= LIBF_DELEXP;
// Can't close yet...
return(NULL);
}
}
/* LibClose(register __a6 struct ClassBase *ClassBase):
*
* Close the library, as called by CloseLibrary()
*/
BPTR __asm __saveds
LibClose(register __a6 struct ClassBase *ClassBase)
{
// Decrement usage count
if(ClassBase -> LibNode . lib_OpenCnt)
ClassBase -> LibNode . lib_OpenCnt--;
// No more users?
if(!ClassBase -> LibNode . lib_OpenCnt && SysBase)
{
// We are going to modify shared data,
// so watch out
ObtainSemaphore(&LockSemaphore);
// Clean up...
if(SoundClass)
{
RemoveClass(SoundClass);
FreeClass(SoundClass);
SoundClass = NULL;
}
if(SuperClassBase)
{
CloseLibrary(SuperClassBase);
SuperClassBase = NULL;
}
if(DataTypesBase)
{
CloseLibrary(DataTypesBase);
DataTypesBase = NULL;
}
if(UtilityBase)
{
CloseLibrary(UtilityBase);
UtilityBase = NULL;
}
if(IFFParseBase)
{
CloseLibrary(IFFParseBase);
IFFParseBase = NULL;
}
if(IntuitionBase)
{
CloseLibrary(IntuitionBase);
IntuitionBase = NULL;
}
if(DOSBase)
{
CloseLibrary(DOSBase);
DOSBase = NULL;
}
// Release the lock
ReleaseSemaphore(&LockSemaphore);
// Can we remove ourselves?
if(ClassBase -> LibNode . lib_Flags & LIBF_DELEXP)
return(LibExpunge(ClassBase));
}
return(NULL);
}
/* LibNull(register __a6 struct ClassBase *ClassBase):
*
* Mandatory dummy function
*/
LONG __asm __saveds
LibNull(register __a6 struct ClassBase *ClassBase)
{
return(NULL);
}
/* GetClassEngine(register __a6 struct ClassBase *ClassBase):
*
* Get access to the class this library implements.
*/
Class * __asm __saveds
GetClassEngine(register __a6 struct ClassBase *ClassBase)
{
Class *class;
// Access shared data
ObtainSemaphore(&LockSemaphore);
// Remember the class pointer
class = SoundClass;
// Release the lock
ReleaseSemaphore(&LockSemaphore);
// Return the pointer
return(class);
}